package com.cosin.serviceImpl;

import com.cosin.dao.mysql.ProjectMapper;
import com.cosin.dao.neo4j.NodeRepository;
import com.cosin.dao.neo4j.RelationRepository;
import com.cosin.model.dto.RiskDataDTO;
import com.cosin.model.po.NodePO;
import com.cosin.service.ScreenService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class ScreenServiceImpl implements ScreenService {

    @Autowired
    private NodeRepository nodeRepository;
    @Autowired
    private RelationRepository relationRepository;

    @Autowired
    private ProjectMapper projectMapper;


    /**
     * 风险级别规划
     * 0.0 ≤ 风险值 < 0.33 低风险
     * 0.33 ≤ 风险值 < 0.67 中风险
     * 0.67 ≤ 风险值 ≤ 1.0 高风险
     */
    public List<RiskDataDTO> companyDistribution(int userId) {
        List<Integer> projectIdList = projectMapper.getProjectIdByUserIdAndPublic(userId);

        // Map<地点, [总风险值, 公司数]>
        Map<String, double[]> locationRiskMap = new HashMap<>();

        for (Integer projectId : projectIdList) {
            List<NodePO> nodePOList = nodeRepository.findByGroupAndProjectId("公司",projectId);
            for (NodePO nodePO : nodePOList) {
                Map<String, String> props = nodePO.getProperties();
                if (props == null) continue;

                String location = props.get("所属省份");
                if (location == null||"".equals( location)) {
                    location = props.get("所属国家");
                }
                String riskValueStr = props.get("风险数值");

                if (location == null || riskValueStr == null) continue;
                double riskValue;
                try {
//                    int riskValue = Integer.parseInt(riskValueStr.trim());
                    riskValue = Double.parseDouble(riskValueStr.trim());
                } catch (NumberFormatException e) {
                    // 非法风险值，跳过
                    // 处理转换失败的情况（例如字符串不是有效的数字格式）
                    System.err.println("字符串格式错误，无法转换为数字: " + riskValueStr);
                    riskValue = 0.0; // 设置一个默认值，根据业务需求调整
                }
                // 初始化或更新
                // 关键修改：使用 double[] 存储总和与数量
                double[] data = locationRiskMap.getOrDefault(location, new double[2]); // [sumRisk(小数), count(整数)]
                data[0] += riskValue; // 累加风险值（保留小数）
                data[1] += 1; // 累加数量（自动转为 double，但实际是整数）
                locationRiskMap.put(location, data);
            }
        }
        System.out.println(locationRiskMap);

        // 构建结果
        List<RiskDataDTO> result = new ArrayList<>();
        for (Map.Entry<String, double[]> entry : locationRiskMap.entrySet()) {
            String location = entry.getKey();
            double[] data = entry.getValue();
            double sumRisk = data[0];
            double count = data[1];
            // 保留三位小数的平均风险计算
            double avgRisk = (count == 0) ? 0 : Math.round((sumRisk / count) * 1000) / 1000.0;

            RiskDataDTO dto = new RiskDataDTO();
            dto.setName(location);
            dto.setCompanyCount(count);
            dto.setRiskValue(avgRisk);
            //如果大于等于0.67，则 riskLevel 为高风险，小于0.67 大于等于 0.33 为中风险，否则为低风险
            dto.setRiskLevel(avgRisk >= 0.67 ? "高风险" : avgRisk >= 0.33 ? "中风险" : "低风险");
            result.add(dto);
        }

        return result;
    }

    //获取风险各个等级数量
    @Override
    public List<RiskDataDTO> riskCount(int userId) {
        List<RiskDataDTO> result = new ArrayList<>();
        List<RiskDataDTO> dataList = companyDistribution(userId); // 每个地点已含 riskLevel、companyCount、name

        for (RiskDataDTO dto : dataList) {
            RiskDataDTO copy = new RiskDataDTO();
            copy.setName(dto.getName());  // 地点
            copy.setRiskLevel(dto.getRiskLevel());  // 风险等级
            copy.setCompanyCount(dto.getCompanyCount());  // 公司数量
            result.add(copy);
        }

        // 降序排序：公司数从多到少
        result.sort((a, b) -> Double.compare(b.getCompanyCount(), a.getCompanyCount()));

        // 返回前10个
        return result.stream().limit(10).toList();
    }



    @Override
    public List<RiskDataDTO> topTenRiskPlace(int userId) {
        List<RiskDataDTO> dataList = companyDistribution(userId);
        dataList.sort((a, b) -> Double.compare(b.getCompanyCount(), a.getCompanyCount()));
        return dataList.subList(0, Math.min(7, dataList.size()));
    }

    /**
     * 风险级别规划
     * 0.0 ≤ 风险值 < 0.33 低风险
     * 0.33 ≤ 风险值 < 0.67 中风险
     * 0.67 ≤ 风险值 ≤ 1.0 高风险
     * @param userId
     * @return
     */
    @Override
    public List<RiskDataDTO> topTenRiskCompany(int userId) {
        List<Integer> projectIdList = projectMapper.getProjectIdByUserIdAndPublic(userId);
        List<RiskDataDTO> result = new ArrayList<>();

        for (Integer projectId : projectIdList) {
            List<NodePO> nodePOList = nodeRepository.findByGroupAndProjectId("公司",projectId);
            for (NodePO node : nodePOList) {
                Map<String, String> props = node.getProperties();
                if (props == null) continue;

                String location = props.get("所属省份");
                if (location == null) {
                    location = props.get("所属国家");
                }
                String name = node.getName();
                String riskStr = props.get("风险数值");

                if (location == null || name == null || riskStr == null) continue;
                double risk;
                try {
                    risk = Double.parseDouble(riskStr.trim());
                } catch (NumberFormatException ignored) {
                    risk = 0;
                    System.out.println("数据格式不正确");
                }
                RiskDataDTO dto = new RiskDataDTO();
                dto.setName(name);
                dto.setCompanyCount(1);
                dto.setRiskValue(risk);
                dto.setRiskLevel(risk >= 0.67 ? "高风险" : risk >= 0.33 ? "中风险" : "低风险");
                dto.setLocation(location);
                result.add(dto);
            }
        }

        result.sort((a, b) -> Double.compare(b.getRiskValue(), a.getRiskValue()));
        return result.subList(0, Math.min(10, result.size()));
    }
    // 获取分别低风险，中风险，高风险数量总和
    @Override
    public List<Integer> countRiskLevel(int userId) {
        int lowCount = 0;
        int mediumCount = 0;
        int highCount = 0;

        List<RiskDataDTO> dataList = companyDistribution(userId);

        for (RiskDataDTO dto : dataList) {
            String level = dto.getRiskLevel();
            double count = dto.getCompanyCount();

            if ("低风险".equals(level)) {
                lowCount += count;
            } else if ("中风险".equals(level)) {
                mediumCount += count;
            } else if ("高风险".equals(level)) {
                highCount += count;
            }
        }

        List<Integer> result = new ArrayList<>();
        result.add(lowCount);
        result.add(mediumCount);
        result.add(highCount);
        return result;
    }


}
